// 最大食物链计数
// a -> b，代表a在食物链中被b捕食
// 给定一个有向无环图，返回
// 这个图中从最初级动物到最顶级捕食者的食物链有几条
// 测试链接 : https://www.luogu.com.cn/problem/P4017

#include <iostream>
#include <vector>
#include <algorithm>
#include <queue>

using namespace std;

int MAXN = 5001;
int MAXM = 500001;
int MOD = 80112002;

vector<int> head(MAXN);
vector<int> Next(MAXM);
vector<int> to(MAXM);
vector<int> indegree(MAXN);
vector<int> lines(MAXN);
int cnt = 1;
int n, m;

void build(int n)
{
    cnt = 1;
    fill(indegree.begin(), indegree.begin() + n + 1, 0);
    fill(lines.begin(), lines.begin() + n + 1, 0);
    fill(head.begin(), head.begin() + n + 1, 0);
}

void addEdge(int u, int v)
{
    Next[cnt] = head[u];
    to[cnt] = v;
    head[u] = cnt++;
}

int ways()
{
    queue<int> q;
    for(int i = 1; i <= n; ++i)
    {
        if(indegree[i] == 0)
        {
            q.push(i);
            lines[i] = 1;
        }
    }

    int ret = 0;
    while(!q.empty())
    {
        int x = q.front();
        q.pop();
        // 当前的 x 节点不再有邻居了
        if(head[x] == 0) ret = (ret + lines[x]) % MOD;
        else
        {
            for(int ei = head[x]; ei; ei = Next[ei])
            {
                int y = to[ei];
                lines[y] = (lines[y] + lines[x]) % MOD;
                if(--indegree[y] == 0) q.push(y);
            }
        }
    }
    return ret;
}

int main()
{
    cin >> n >> m;
    build(n);
    for(int i = 0; i < m; ++i)
    {
        int from, to;
        cin >> from >> to;
        addEdge(from, to);
        ++indegree[to];
    }
    cout << ways() << endl;
    return 0;
}